package com.help10000.rms.ui.fragments

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.PixelFormat
import android.media.MediaScannerConnection
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.Looper
import android.view.View
import android.webkit.CookieManager
import android.webkit.CookieSyncManager
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import com.amir.common.api.CustomObserver
import com.amir.common.api.upload.FileUploadObserver
import com.amir.common.beans.CompanyEntity
import com.amir.common.beans.FileEntity
import com.amir.common.mvp.model.Model
import com.amir.common.utils.AppManager
import com.amir.common.utils.AppVersionUtils
import com.amir.common.utils.Constant
import com.amir.common.utils.LogUtils
import com.amir.common.utils.SPUtils
import com.amir.common.utils.Utils
import com.github.lzyzsd.jsbridge.BridgeWebViewClient
import com.github.lzyzsd.jsbridge.CallBackFunction
import com.help10000.kottlinbaselib.api.upload.UploadFileRequestBody
import com.help10000.rms.R
import com.help10000.rms.common.WeChatPresenter
import com.help10000.rms.mvp.presenter.MyWebViewPresenter
import com.help10000.rms.mvp.view.MyWebViewView
import com.help10000.rms.ui.activitys.ImagePreviewActivity
import com.help10000.rms.ui.activitys.MainActivity
import com.help10000.rms.ui.activitys.MyWebViewActivity
import com.help10000.rms.ui.activitys.ScanActivity
import com.help10000.rms.ui.activitys.SelectCompanyActivity
import com.help10000.rms.ui.activitys.logins.LoginActivity
import com.help10000.rms.ui.base.BaseFragment
import com.help10000.rms.ui.utils.ImageCompressor
import com.help10000.rms.ui.utils.PageUtils
import com.help10000.rms.ui.utils.StatusBarUtil
import com.help10000.rms.utils.LocationManager
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanOptions
import com.tencent.map.geolocation.TencentLocation
import com.tencent.map.geolocation.TencentLocationListener
import com.tencent.map.geolocation.TencentLocationManager
import com.tencent.map.geolocation.TencentLocationRequest
import com.ypx.imagepicker.ImagePicker
import com.ypx.imagepicker.bean.MimeType
import io.reactivex.android.schedulers.AndroidSchedulers
import kotlinx.android.synthetic.main.actvity_my_webview.*
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import org.json.JSONObject
import java.io.File
import java.io.FileOutputStream
import java.net.URLEncoder


class WebFragment : BaseFragment<MyWebViewPresenter, MyWebViewView>(), MyWebViewView {

    private var mUrl: String? = null
    private var mColor: String?= null
    private var mCameraTempFile: File? = null

    private var pendingScanCallback: CallBackFunction? = null
    private var pendingCameraCallback: CallBackFunction? = null

    override fun createPresenter() = MyWebViewPresenter(this)
    override fun getlayoutId(): Int {
        return R.layout.fragment_web
    }

    private val scanLauncher = registerForActivityResult(ScanContract()) { result ->
        pendingScanCallback?.apply {
            val json = if (result.contents != null) JSONObject().apply {
                put("code", 1); put("msg", "扫描成功"); put("result", JSONObject().apply { put("content", result.contents) })
            } else JSONObject().apply {
                put("code", 0); put("msg", "扫描失败"); put("result", JSONObject())
            }
            onCallBack(json.toString())
            pendingScanCallback = null
        }
    }

    // 在Fragment类中定义相机启动器
    private val cameraLauncher = registerForActivityResult(ActivityResultContracts.TakePicture()) { success ->
        if (success && mCameraTempFile?.exists() == true) {
            // 拍照成功，处理图片
            compressJPG(mCameraTempFile!!)
            val contentUri = FileProvider.getUriForFile(
                requireContext(),
                "${requireContext().packageName}.FileProvider",
                mCameraTempFile!!
            )
            // 回调JS
            pendingCameraCallback?.onCallBack(JSONObject().apply {
                put("code", 1)
                put("msg", "拍摄成功")
                put("result", JSONObject().apply { put("path", contentUri.toString()) })
            }.toString())
            // 刷新媒体库
            MediaScannerConnection.scanFile(
                requireContext(),
                arrayOf(mCameraTempFile!!.absolutePath),
                arrayOf("image/jpeg"),
                null
            )
        } else {
            // 拍照失败或取消
            pendingCameraCallback?.onCallBack(
                JSONObject().apply {
                    put("code", 0)
                    put("msg", "拍摄失败")
                    put("result", JSONObject())
                }.toString()
            )
        }
        pendingCameraCallback = null
        mCameraTempFile = null
    }


    override fun initData(savedInstanceState: Bundle?) {

    }

    override fun initView(rootView: View?) {
        this.init()
        this.initWebView()
        this.initBridgeHandler()
    }

    private fun init(){
        arguments?.let {
            mUrl = it.getString(ARG_URL)
            mColor = it.getString(ARG_COLOR)
        }

        //TODO 测试代码
        //mUrl = "file:///android_asset/test_bridge.html"
        if(mUrl.isNullOrEmpty()){
            return
        }
        pwv_webview.settings.javaScriptEnabled = true
        pwv_webview.settings.blockNetworkImage = false
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0开始，https不能加载http资源，需要添加一下代码
            pwv_webview.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW;
        }
        // 设置 Cookie
        initCookie(mUrl!!)

    }

    private fun initCookie(url: String) {
        val accessToken = SPUtils.getString(Constant.AccessToken)
        // 构造 Cookie 字符串，例如："accessToken=your_access_token_value"
        //val cookieString = "AccessToken=$accessToken"
        val cookieString = "AccessToken=$accessToken; path=/; domain=.help10000.com"

        val cookieManager = CookieManager.getInstance()
        cookieManager.removeAllCookie()
        cookieManager.setAcceptCookie(true)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            cookieManager.setAcceptThirdPartyCookies(pwv_webview, true)
        }

        cookieManager.setCookie("http://m.help10000.com", cookieString)
        LogUtils.I("TrackMenu WebFragment initCookie http://m.help10000.com : $cookieString")
        // 兼容异步处理（Android 5.0+ 需要 flush）
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            cookieManager.flush()
        } else {
            CookieSyncManager.createInstance(activity)
            CookieSyncManager.getInstance().sync()
        }
        val cookieValue = CookieManager.getInstance().getCookie("http://m.help10000.com")
        LogUtils.I("TrackMenu WebFragment getCookie $cookieValue")
        val cookieValue2 = CookieManager.getInstance().getCookie(mUrl)
        LogUtils.I("TrackMenu WebFragment getCookie2 $cookieValue2")
    }


    private fun initBridgeHandler(){
        pwv_webview.registerHandler("xUploadImage") { data: String, callBackFunction: CallBackFunction ->
            ImagePicker.withMulti(WeChatPresenter())//设置presenter
                .setMaxCount(1)//设置选择数量
                .showCamera(true)//设置显示拍照
                .setPreview(true)
                .setColumnCount(4)//设置列数
                .mimeTypes(MimeType.ofImage())//设置需要加载的文件类型
                .filterMimeTypes(MimeType.GIF)//设置需要过滤掉的文件类型
                .setVideoSinglePick(true)//设置视频单选
                .setMaxVideoDuration(1200000L)//设置可选区的最大视频时长
                .setMinVideoDuration(60000L)//设置视频可选取的最小时长
                .pick(activity) { items ->
                    if (items.size > 0) {
                        val file = File(items[0].path)
                        LogUtils.I("TrackCom WebFragment", "file: ${file.path}")
                        ImageCompressor.compressAsync(Utils.getContext(), file)
                            .onErrorReturn { file }
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe({ compressedFile ->
                                LogUtils.I(
                                    "TrackCom WebFragment",
                                    "compressedFile: ${compressedFile.path} ${compressedFile.name}"
                                )
                                LogUtils.I(
                                    "TrackCom WebFragment",
                                    "compressedFile exists: ${compressedFile.exists()}" +
                                            " ${compressedFile.canRead()}"+
                                            " ${compressedFile.canWrite()}"
                                )
                                val accessToken = SPUtils.getString(Constant.AccessToken)
                                val requestBody =
                                    UploadFileRequestBody(compressedFile, mFileUploadObserver)
                                val part = MultipartBody.Part.createFormData(
                                    "file",
                                    URLEncoder.encode(compressedFile.name,"utf-8"),
                                    requestBody
                                )
                                val result = Model.getServer().UploadFile(accessToken, part)
                                Model.getObservable(
                                    result,
                                    object : CustomObserver<FileEntity>(mvpView) {
                                        override fun success(t: FileEntity) {
                                            callBackFunction.onCallBack(t.FileName)
                                        }
                                    })
                            }, { error ->
                                LogUtils.I(
                                    "TrackCom WebFragment",
                                    "图片压缩失败: ${error.message}"
                                )
                            })
                    }
                }

        }

        pwv_webview.registerHandler("xShowLoading"){ data: String, _: CallBackFunction ->
            if(data == "true"){
                (activity as MainActivity).showLoading()
            }else{
                 (activity as MainActivity).dismissLoading()
            }
        }

        //进入首页
        pwv_webview.registerHandler("xGoHome"){ url: String, _: CallBackFunction ->
            LogUtils.I("TrackMenu WebFragment pwv_webview xGoHome")
             (activity as MainActivity).switchToHome(url)
        }

        pwv_webview.registerHandler("xGoLogin"){ _: String, _: CallBackFunction ->
            // JS 调用示例: window.WebViewJavascriptBridge.callHandler('xGoHome');
            LogUtils.I("TrackMenu WebFragment pwv_webview xGoLogin")
            SPUtils.remove(Constant.pwd)
            SPUtils.remove(Constant.CmpyCode)
            SPUtils.remove(Constant.encodePassword)
            AppManager.getAppManager().finishAllActivity()
            PageUtils.jumpToActivity(context, LoginActivity::class.java)
             (activity as MainActivity).finish()
        }

        pwv_webview.registerHandler("xGoLoginCompany"){ _: String, _: CallBackFunction ->
            LogUtils.I("TrackMenu WebFragment pwv_webview xGoLoginCompany")
            fetchCompanyList()
        }

        pwv_webview.registerHandler("xScan"){ data: String, callBackFunction: CallBackFunction ->
            LogUtils.I("TrackMenu WebFragment pwv_webview xScan")
            pendingScanCallback = callBackFunction
            //调起摄像头，扫描二维码或条形码，并识别
            checkPermissionAndStartScan()
        }

        //5. xCamera 拍照
        pwv_webview.registerHandler("xCamera") { _, cb ->
            // JS 调用示例:
            // window.WebViewJavascriptBridge.callHandler('xCamera', '', function(data){ ... });
            LogUtils.I("TrackMenu WebFragment pwv_webview xCamera")
            pendingCameraCallback = cb
            checkPermissionAndCamera();
        }

        // 6. xPreviewPicture 图片预览
        pwv_webview.registerHandler("xPreviewPicture") { data, _ ->
            // JS 调用示例: window.WebViewJavascriptBridge.callHandler('xPreviewPicture', ['path1','path2']);

            LogUtils.I("TrackMenu WebFragment pwv_webview xPreviewPicture $data")
            startActivity(Intent(context, ImagePreviewActivity::class.java)
                .putExtra("imageUris", data))
        }

        // 7. xLocation 定位
        pwv_webview.registerHandler("xLocation") { _, cb ->
            LogUtils.I("TrackMenu WebFragment pwv_webview xLocation")
            // JS 调用示例:
            // window.WebViewJavascriptBridge.callHandler('xLocation','',function(data){...});

            requestLocation(cb)
//            LocationManager.getLocationForJS(this) { json ->
//                cb.onCallBack(json) // 直接返回JSON给JS
//            }
        }


        pwv_webview.registerHandler("xSetStatusBar") { colorHex, cb ->
            LogUtils.I("TrackMenu MyWebViewActivity pwv_webview xSetStatusBar $colorHex")
            // JS 调用示例:
            activity?.let { StatusBarUtil.setColor(it, colorHex) }
        }
    }

    private fun fetchCompanyList() {
        val accountid = SPUtils.getString(Constant.accountid)
        val accessToken = SPUtils.getString(Constant.AccessToken)
        val loginCompanyList = Model.getServer().LoginCompanyList(accessToken!!, "6666", accountid)
        Model.getObservable(loginCompanyList, object : CustomObserver<CompanyEntity>(mvpView) {

            override fun success(t: CompanyEntity) {
                /**
                 * 跳转公司
                 */
                val intent = Intent(mContext, SelectCompanyActivity::class.java)
                intent.putExtra("data", t.data)
                intent.putExtra("flag", 1)
                startActivity(intent)
            }
        })
    }

    private fun initWebView(){
        LogUtils.I("TrackCom WebFragment", "initView")
        activity?.window?.setFormat(PixelFormat.TRANSLUCENT)
        val webSettings = pwv_webview.settings
        webSettings?.javaScriptEnabled = true

        webSettings.domStorageEnabled = true // 打开本地缓存提供JS调用,至关重要
        webSettings.allowFileAccess = true
        webSettings.allowContentAccess = true
        webSettings.databaseEnabled = true

        webSettings.textZoom = 100;
        webSettings.useWideViewPort = true;
        webSettings.loadWithOverviewMode = true;
        //webSettings.cacheMode = WebSettings.LOAD_NO_CACHE;
        // ⬇️ 允许 file:// 页面跨协议访问 content://、http:// 等
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            webSettings.allowFileAccessFromFileURLs = true
            webSettings.allowUniversalAccessFromFileURLs = true
        }

        webSettings.userAgentString = webSettings.userAgentString + " shabei/" + AppVersionUtils.getAppVersionName(requireContext())

        pwv_webview.webViewClient = object : BridgeWebViewClient(pwv_webview){

            override fun onPageFinished(view: WebView?, url: String?) {
                LogUtils.I("TrackMenu WebFragment onPageFinished $url")
                super.onPageFinished(view, url)
            }

            @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
            override fun shouldOverrideUrlLoading(
                view: WebView?,
                request: WebResourceRequest?
            ): Boolean {
                val newUrl = request?.url?.toString()
                LogUtils.I("TrackCom WebFragment", "newUrl: $newUrl")
                LogUtils.I("TrackCom WebFragment", "mUrl: $mUrl")
                if (newUrl != null) {
                    if((newUrl.startsWith("http") || newUrl.startsWith("file"))
                        && newUrl != mUrl){
                        startActivity(Intent(activity, MyWebViewActivity::class.java).apply {
                            putExtra("url", newUrl)
                            putExtra("color", mColor)
                        })
                        return true
                    }
                }
                return super.shouldOverrideUrlLoading(view, request)
            }
        }

        this.mUrl?.let { pwv_webview.loadUrl(it) }
    }

    private val mFileUploadObserver = object : FileUploadObserver<ResponseBody>(mvpView) {
        override fun onUpLoadSuccess(t: ResponseBody) {

        }

        override fun onUpLoadFail(e: Throwable) {

        }

        override fun onProgress(progress: Int) {

        }
    }

    private fun compressJPG(file:File) {
        // 1. 解码成 Bitmap（可做采样以节省内存）
        val options = BitmapFactory.Options().apply {
            inJustDecodeBounds = false
            inSampleSize = 1  // 根据需要设置缩放
        }
        val bitmap = BitmapFactory.decodeFile(file.absolutePath, options)
        // 2. 写回文件，compress 到 80%
        FileOutputStream(file).use { out ->
            bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out)
        }
    }

    // 检查相机权限并启动扫码
    private fun checkPermissionAndStartScan() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED
            ) {
                // 没有权限，申请
                requestPermissions(arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
            } else {
                // 已授权，直接开始扫码
                startScan()
            }
        } else {
            // Android 5.x 及以下系统，无需权限申请，直接开始扫码
            startScan()
        }
    }

    private fun startScan() {
        val options = ScanOptions().apply {
            setDesiredBarcodeFormats(
                ScanOptions.QR_CODE,
                ScanOptions.CODE_39,
                ScanOptions.CODE_128,
                ScanOptions.EAN_13,
                ScanOptions.EAN_8,
                ScanOptions.UPC_A,
                ScanOptions.ITF
            )
            setPrompt("将二维码/条形码放入框内")
            setCameraId(0)
            setBeepEnabled(true)
            // 这里虽然还可以再调一次，但最关键是下面这一行
            //requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT // 强制竖屏
            // 指定我们刚才写的、自带返回按钮的竖屏 Activity
            setCaptureActivity(ScanActivity::class.java)
        }
        scanLauncher.launch(options)
    }

    // 检查相机权限并启动扫码
    private fun checkPermissionAndCamera() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED
            ) {
                // 没有权限，申请
                requestPermissions(arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
            } else {
                // 已授权，直接开始扫码
                openCamera()
            }
        } else {
            // Android 5.x 及以下系统，无需权限申请，直接开始扫码
            openCamera()
        }
    }


    private fun openCamera() {
        val cameraDir = File(
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
            "Camera"
        ).apply { if (!exists()) mkdirs() }

        val photoFile = File(cameraDir, "IMG_${System.currentTimeMillis()}.jpg")

        try {
            mCameraTempFile = photoFile
            val uri = FileProvider.getUriForFile(requireContext(), "${requireContext().packageName}.FileProvider", photoFile)
            //启动相机
            cameraLauncher.launch(uri)
        }
        catch (e: Exception) {
            e.printStackTrace()
            pendingCameraCallback?.onCallBack(JSONObject().apply {
                put("code", 0)
                put("msg", "拍摄失败")
                put("result", JSONObject())
            }.toString())
            pendingCameraCallback = null
        }
    }

    private fun requestLocation(cb: CallBackFunction) {
        val mLocationManager = TencentLocationManager.getInstance(activity)
        val request = TencentLocationRequest.create()
        //是否允许使用GPS
        request.isAllowGPS =true
        //是否需要获取传感器方向
        request.isAllowDirection =true
        //是否需要开启室内定位
        request.setIndoorLocationMode(true)

        mLocationManager.requestSingleFreshLocation(
            request,
            object : TencentLocationListener {
                override fun onStatusUpdate(p0: String?, p1: Int, p2: String?) {
                    LogUtils.I("P0:$p0\nP1:$p1\nP2:$p2 ")
                }

                override fun onLocationChanged(tencentLocation: TencentLocation?, p1: Int, p2: String?) {
                    LogUtils.I("P0:$tencentLocation\nP1:$p1\nP2:$p2 ")
                    if (tencentLocation != null) {
//                        SPUtils.save(Constant.Latitude, tencentLocation.latitude)
//                        SPUtils.save(Constant.Longitude, tencentLocation.longitude)
                        SPUtils.save(Constant.Accuracy, tencentLocation.accuracy)

                        val lat = tencentLocation.latitude
                        val lng = tencentLocation.longitude
                        val json = if (lat>=0 && lng>=0) {
                            JSONObject().apply {
                                put("code", 1)
                                put("msg", "实时定位成功")
                                put("result", JSONObject().apply {
                                    put("lng", lng.toString())
                                    put("lat", lat.toString())
                                })
                            }.toString()
                        } else {
                            JSONObject().apply {
                                put("code", 0)
                                put("msg", "实时定位失败")
                                put("result", JSONObject().apply {
                                    put("lng", "0")
                                    put("lat", "0")
                                })
                            }.toString()
                        }
                        cb.onCallBack(json)
                    }
                }
            },
            Looper.getMainLooper()
        )
    }

    // 动态权限申请结果回调
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 权限授予，开始扫码
                startScan()
            } else {
                // 权限被拒绝，回调 JS 失败信息
                pendingScanCallback?.onCallBack(JSONObject().apply {
                    put("code", 0)
                    put("msg", "扫描失败：PERMISSION_DENIED")
                    put("result", JSONObject())
                }.toString())
                pendingScanCallback = null
            }
        }
    }

    fun reload() {
        this.mUrl?.let { pwv_webview.loadUrl(it) }
        LogUtils.I("TrackCom WebFragment", "reload:")
    }

    fun loadBlank() {
        //pwv_webview.loadUrl("about:blank")
        //LogUtils.I("TrackCom WebFragment", "loadBlank:")
    }


    companion object {
        private const val ARG_URL = "url"
        private const val ARG_COLOR = "color"
        private const val REQUEST_CAMERA = 1001
        private const val REQUEST_CAMERA_PERMISSION = 1002

        @JvmStatic fun newInstance(url: String, statusBarColor: String) =
            WebFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_URL, url)
                    putString(ARG_COLOR, statusBarColor)
                }
            }
    }
}
